﻿// ***********************************************************************
// Assembly         : Tx.OCC
// Author           : tianteng
// Created          : 09-06-2019
//
// Last Modified By : tianteng
// Last Modified On : 09-06-2019
// ***********************************************************************
// <copyright file="OccEdgeEx.cs" company="北京腾雪科技有限责任公司">
//     Copyright © 北京腾雪科技有限责任公司 2022
// </copyright>
// <summary></summary>
// ***********************************************************************
using Occt;
using System.Collections.Generic;
using System.Linq;

namespace Tx.OCC
{
    /// <summary>
    /// Class OccEdgeEx.
    /// </summary>
    public static class OccEdgeEx
    {
        /// <summary>
        /// Firsts the vertex.
        /// </summary>
        /// <param name="edge">The edge.</param>
        /// <returns>TopoDS_Vertex.</returns>
        public static TopoDS_Vertex FirstVertex(this TopoDS_Edge edge)
        {
            return TopExp.FirstVertex(edge);
        }
        /// <summary>
        /// Lasts the vertex.
        /// </summary>
        /// <param name="edge">The edge.</param>
        /// <returns>TopoDS_Vertex.</returns>
        public static TopoDS_Vertex LastVertex(this TopoDS_Edge edge)
        {
            return TopExp.LastVertex(edge);
        }

        /// <summary>
        /// Gets the type of the edge.
        /// </summary>
        /// <param name="edge">The edge.</param>
        /// <returns>CurveType.</returns>
        public static GeomAbs_CurveType GetCurveType(this TopoDS_Edge edge)
        {
            return new BRepAdaptor_Curve(edge).Type;
        }
        /// <summary>
        /// Searches for the longest edge of a shape, and find the longest parallel edge
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <returns>System.ValueTuple&lt;TopoDS_Edge, System.Nullable&lt;gp_Ax1&gt;, TopoDS_Edge, System.Nullable&lt;gp_Ax1&gt;&gt;.</returns>
//         public static (TopoDS_Edge edge, gp_Ax1 axis, TopoDS_Edge opEdge, gp_Ax1 opAxis) FindLongestEdge(TopoDS_Shape shape)
//         {
//             TopoDS_Edge foundEdge = null;
//             gp_Ax1 foundAxis = null;
//             TopoDS_Edge opEdge = null;
//             gp_Ax1 opAxis = null;
// 
//             // Find the longest edge to revolve around
//             double edgeLen = -1;
//             var edgeInfos = new List<(TopoDS_Edge edge, double len, gp_Ax1 axis)>();
//             var edges = shape.Edges();
//             foreach (var edge in edges)
//             {
//                 var brepAdaptor = new BRepAdaptor_Curve(edge);
//                 if (brepAdaptor.Type != GeomAbs_CurveType.GeomAbs_Line)
//                     break;
// 
//                 var v1 = brepAdaptor.Value(brepAdaptor.FirstParameter);
//                 var v2 = brepAdaptor.Value(brepAdaptor.LastParameter);
//                 var len = v1.Distance(v2);
//                 var axis = new gp_Ax1(v1, new gp_Dir(new gp_Vec(v1, v2)));
//                 if (edge.Orientation == TopAbs_Orientation.TopAbs_REVERSED)
//                 {
//                     axis.Reverse();
//                 }
//                 edgeInfos.Add((edge, len, axis));
// 
//                 if (foundEdge != null && foundEdge.IsSame(edge))
//                 {
//                     // Same edge with another orientation
//                     if (foundEdge.Orientation == TopAbs_Orientation.TopAbs_REVERSED
//                         && edge.Orientation == TopAbs_Orientation.TopAbs_FORWARD)
//                     {
//                         // Prefer forward edges
//                         foundEdge = edge;
//                     }
//                     continue;
//                 }
// 
//                 if (len > edgeLen)
//                 {
//                     foundEdge = edge;
//                     edgeLen = len;
//                     foundAxis = axis;
//                 }
//             }
// 
//             if (foundAxis != null)
//             {
//                 // Find opposite edge
//                 edgeLen = -1;
//                 foreach (var ei in edgeInfos)
//                 {
//                     if (ei.edge == foundEdge)
//                         continue;
//                     if (!ei.axis.IsParallel(foundAxis, 0.00001))
//                         continue;
// 
//                     if (ei.len > edgeLen)
//                     {
//                         opEdge = ei.edge;
//                         edgeLen = ei.len;
//                         opAxis = ei.axis;
//                     }
//                 }
//             }
//             return (foundEdge, foundAxis, opEdge, opAxis);
//         }



        /// <summary>
        /// Searches for the smallest and biggest adjacent face
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <param name="edgeShape">The edge shape.</param>
        /// <returns>System.ValueTuple&lt;TopoDS_Face, TopoDS_Face&gt;.</returns>
//         public static (TopoDS_Face smallestFace, TopoDS_Face largestFace) FindSmallestAndLargestAdjacentFaces(TopoDS_Shape shape, TopoDS_Edge edgeShape)
//         {
//             // Create a Map of Edge and connected Faces
//             TopExp.MapShapesAndAncestors(shape, TopAbs_ShapeEnum.TopAbs_EDGE, TopAbs_ShapeEnum.TopAbs_FACE, out var mapOfEdgesToFaces);
// 
//             var faceDict = new Dictionary<TopoDS_Face, double>();
// 
//             var faces = mapOfEdgesToFaces.FindFromKey(edgeShape).ToList();
//             foreach (var face in faces)
//             {
//                 BRepGProp.SurfaceProperties(face, out GProp_GProps gprops, false);
//                 faceDict.Add(face.ToFace(), gprops.Mass);
//             }
// 
//             if (!faceDict.Any())
//                 return (null, null);
// 
//             var min = faceDict.First();
//             var max = min;
//             foreach (var kvp in faceDict.Skip(1))
//             {
//                 if (kvp.Value < min.Value)
//                     min = kvp;
//                 if (kvp.Value > max.Value)
//                     max = kvp;
//             }
// 
//             return (min.Key, max.Key);
//         }



        /// <summary>
        /// Searches for adjacent faces
        /// </summary>
        /// <param name="shape">The shape.</param>
        /// <param name="edgeShape">The edge shape.</param>
        /// <returns>System.ValueTuple&lt;TopoDS_Face, TopoDS_Face&gt;.</returns>
//         public static (TopoDS_Face face1, TopoDS_Face face2) FindAdjacentFaces(TopoDS_Shape shape, TopoDS_Edge edgeShape)
//         {
//             // Create a Map of Edge and connected Faces
//             TopExp.MapShapesAndAncestors(shape, TopAbs_ShapeEnum.TopAbs_EDGE, TopAbs_ShapeEnum.TopAbs_FACE, out var mapOfEdgesToFaces);
// 
//             var faces = mapOfEdgesToFaces.FindFromKey(edgeShape).ToList();
//             var face1 = faces.Count > 0 ? faces[0].ToFace() : null;
//             var face2 = faces.Count > 1 ? faces[1].ToFace() : null;
//             return (face1, face2);
//         }



        /// <summary>
        /// Finds the shared vertex.
        /// </summary>
        /// <param name="edge1">The edge1.</param>
        /// <param name="edge2">The edge2.</param>
        /// <returns>TopoDS_Vertex.</returns>
        public static TopoDS_Vertex FindSharedVertex(TopoDS_Edge edge1, TopoDS_Edge edge2)
        {
            var vertices1 = edge1.Vertices();
            var vertices2 = edge2.Vertices();
            foreach (var vertex in vertices1)
            {
                if (vertices2.Any(v => v.IsSame(vertex)))
                    return vertex;
            }
            return null;
        }
    }
}
